package com.csw.compose.ui.module.animation

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandIn
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.animation.shrinkOut
import androidx.compose.animation.slideIn
import androidx.compose.animation.slideOut
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import com.csw.compose.theme.pagePadding
import com.csw.compose.ui.Destination
import com.csw.compose.ui.components.BodyText
import com.csw.compose.ui.components.LabelText
import com.csw.compose.ui.components.LargeSpacer
import com.csw.compose.ui.components.NormalSpacer
import com.csw.compose.ui.components.OlItem
import com.csw.compose.ui.components.PrimaryTitle
import com.csw.compose.ui.components.UlItem
import com.csw.compose.ui.module.BasePage

@Preview(heightDp = 2000)
@Composable
fun VisibilityAnimationPagePreview() {
    BasePage({}, "可见性动画") {
        VisibilityAnimationPage()
    }
}

class VisibilityAnimationPageData {
    companion object : Destination("VisibilityAnimationPage")
}

@Composable
fun VisibilityAnimationPage() {
    Column(
        modifier = Modifier
            .padding(horizontal = pagePadding)
            .verticalScroll(rememberScrollState())
    ) {
        PrimaryTitle("简介")
        BodyText("可见性改变时执行动画，若不可见，在动画结束时会将组合移除")
        NormalSpacer()

        var visible by remember { mutableStateOf(true) }
        AnimatedVisibility(visible) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(150.dp)
                    .alpha(0.3f)
                    .background(Color.Red)
            )
        }
        Button({
            visible = !visible
        }) {
            Text("切换状态")
        }
        UlItem("AnimatedVisibility")
        LabelText("该组件用于实现内容可见性发生变化时执行动画")
        LabelText("适用于频繁显示隐藏的组件")

        NormalSpacer()
        OlItem(1, "visible")
        LabelText("控制组件可见性，只有可见与不可见两种状态")

        NormalSpacer()
        OlItem(2, "enter")
        LabelText("组件可见时执行的进入动画，默认是淡入+展开")

        NormalSpacer()
        OlItem(3, "exit")
        LabelText("组件不可见时执行的退出动画，默认是淡出+收起")

        LargeSpacer()
        UlItem("EnterTransition ExitTransition")
        LabelText("compose内部定义了组件进入与退出过渡动画的描述类。")
        LabelText("compose定义了一套方法用于创建动画，通过变换实现的组件动画有以下四种，xxxIn表示进入动画，xxxOut表示退出动画。")

        NormalSpacer()
        OlItem(1, "fadeIn fadeOut")
        LabelText("通过透明度属性实现的淡入淡出")
        var fade by remember { mutableStateOf(true) }
        Row(verticalAlignment = Alignment.CenterVertically) {
            AnimatedVisibility(
                fade,
                enter = fadeIn(),
                exit = fadeOut()
            ) {
                Box(
                    modifier = Modifier
                        .size(60.dp)
                        .alpha(0.3f)
                        .background(Color.Red)
                )
            }
            Button({
                fade = !fade
            }) {
                Text("切换状态")
            }
        }

        NormalSpacer()
        OlItem(2, "slideIn slideOut")
        LabelText("通过修改偏移量实现的滑动进入与退出")
        LabelText("compose 提供了Vertically Horizontally两个版本的方法可以快速实现纵向与横向的滑动动画")
        LabelText("要注意，动画描述对象复写了plus方法使得可以通过+操作符来同时执行多个动画效果，但相同属性的动画是互相覆盖的，若要实现从对角线进入和退出，不可以直接用水平进入+垂直进入")
        var slide by remember { mutableStateOf(true) }
        Row(verticalAlignment = Alignment.CenterVertically) {
            AnimatedVisibility(
                slide,
                enter = slideIn(spring()) { IntOffset(-it.width, -it.height) },
                exit = slideOut(spring()) { IntOffset(it.width, it.height) }
            ) {
                Box(
                    modifier = Modifier
                        .size(60.dp)
                        .alpha(0.3f)
                        .background(Color.Red)
                )
            }
            Button({
                slide = !slide
            }) {
                Text("切换状态")
            }
        }

        NormalSpacer()
        OlItem(3, "scaleIn scaleOut")
        LabelText("通过修改缩放属性实现的缩放动画")
        var scale by remember { mutableStateOf(true) }
        Row(verticalAlignment = Alignment.CenterVertically) {
            AnimatedVisibility(
                scale,
                enter = scaleIn(),
                exit = scaleOut(),
            ) {
                Box(
                    modifier = Modifier
                        .size(60.dp)
                        .alpha(0.3f)
                        .background(Color.Red)
                )
            }
            Button({
                scale = !scale
            }) {
                Text("切换状态")
            }
        }


        NormalSpacer()
        OlItem(4, "expandIn shrinkOut")
        LabelText("通过修改尺寸实现展开与收起动画，同样compose也提供了纵向与横向的实现版本，用于快速实现动画效果")
        var size by remember { mutableStateOf(true) }
        Row(verticalAlignment = Alignment.CenterVertically) {
            AnimatedVisibility(
                size,
                enter = expandIn(),
                exit = shrinkOut(tween()),
            ) {
                Box(
                    modifier = Modifier
                        .size(60.dp)
                        .alpha(0.3f)
                        .background(Color.Red)
                )
            }
            Button({
                size = !size
            }) {
                Text("切换状态")
            }
        }

        LargeSpacer()
        UlItem("AnimationSpec")
        LabelText("动画规范，以前在Android原生动画中，我们可以设置加速器来调整动画效果，使得动画不是僵硬的线性过渡")
        LabelText("compose通过AnimationSpec来实现，常见的有以下两种")

        NormalSpacer()
        OlItem(1, "tween")
        LabelText("这个跟Android系统动画基本一样，设置动画时间、动画效果")

        NormalSpacer()
        OlItem(2, "spring")
        LabelText("以上面的slide动画例子，具备弹簧的物理效果，对比tween在切换不同动画时，组件拥有连贯的速度改变，而不是直接抛弃之前的状态以新的方向朝着动画目的地运动")
        LabelText("dampingRatio 弹簧阻尼，可以调节产生的振荡效果")
        LabelText("stiffness 弹簧刚度，刚度越高，执行动画时组件将以标准的时间到达目的地，而刚度低的弹簧，就会表现为拿着一条比较软的弹簧拉扯组件，它会延迟一些到达")



    }
}